/*
 * @[H]:  Copyright (c) 2021 Phytium Information Technology, Inc. 
 * 
 *  SPDX-License-Identifier: Apache-2.0. 
 * 
 * @Date: 2021-07-13 16:37:29
 * @LastEditTime: 2021-07-16 13:44:53
 * @Description:  Description of file
 * @Modify History: 
 * * * Ver   Who        Date         Changes
 * * ----- ------     --------    --------------------------------------
 */

#ifndef BSP_DRIVERS_F_SPI_HW_H
#define BSP_DRIVERS_F_SPI_HW_H

#ifdef __cplusplus
extern "C"
{
#endif

#include "parameters.h"
#include "ft_io.h"

/* offset map of SPI register */
#define FSPI_CTRL_R0_OFFSET 0x00       //Ctrl register 0
#define FSPI_CTRL_R1_OFFSET 0x04       //Ctrl register 1
#define FSPI_SSIENR_OFFSET 0x08        //SPI enable register
#define FSPI_MWCR_OFFSET 0x0c          //Microwire ctrl register
#define FSPI_SER_OFFSET 0x10           //Slave enable register
#define FSPI_BAUD_R_OFFSET 0x14        //Baudrate set register
#define FSPI_TXFTL_R_OFFSET 0x18       //Tx threshold register
#define FSPI_RXFTL_R_OFFSET 0x1c       //Rx threshold register
#define FSPI_TXFLR_OFFSET 0x20         //Tx level register
#define FSPI_RXFLR_OFFSET 0x24         //Rx level register
#define FSPI_SR_OFFSET 0x28            //Status register
#define FSPI_IMR_OFFSET 0x2c           //Intr mask register
#define FSPI_ISR_OFFSET 0x30           //Irq Status register
#define FSPI_RIS_R_OFFSET 0x34         //Intr status register
#define FSPI_TXOI_CR_OFFSET 0x38       //TX FIFO overflow intr clear register
#define FSPI_RXOI_CR_OFFSET 0x3c       //RX FIFO overflow intr clear register
#define FSPI_RXUI_CR_OFFSET 0x40       //TX FIFO underflow intr clear register
#define FSPI_MSTI_CR_OFFSET 0x44       //Multi slave intr clear register
#define FSPI_ICR_OFFSET 0x48           //Intr clear register
#define FSPI_DMA_CR_OFFSET 0x4c        //DMA ctrl register
#define FSPI_DMA_TDLR_OFFSET 0x50      //DMA TX Data level register
#define FSPI_DMA_RDLR_OFFSET 0x54      //DMA RX Data level register
#define FSPI_IDR_OFFSET 0x58           //Identification register
#define FSPI_DR_OFFSET 0x60            //Data register
#define FSPI_RX_SAMPLE_DLY_OFFSET 0xfc //RX Data delay register

#define FRF_OFFSET 4
#define MODE_OFFSET 6
#define TMOD_OFFSET 8

#define INT_TXEI (1 << 0)
#define INT_TXOI (1 << 1)
#define INT_RXUI (1 << 2)
#define INT_RXOI (1 << 3)

#define SPI_TMOD_OFFSET 8
#define SPI_TMOD_MASK (0x3 << SPI_TMOD_OFFSET)
#define SPI_TMOD_TR 0x0        /* xmit & recv */
#define SPI_TMOD_TO 0x1        /* xmit only */
#define SPI_TMOD_RO 0x2        /* recv only */
#define SPI_TMOD_EPROMREAD 0x3 /* eeprom read mode */

    /***************** Macros (Inline Functions) Definitions *********************/

#define FSPI_READREG32(addr, reg_offset) FtIn32(addr + (u32)reg_offset)
#define FSPI_WRITEREG32(addr, reg_offset, reg_value) FtOut32(addr + (u32)reg_offset, (u32)reg_value)

    static _INLINE void FSpiIrqMask(u32 base_addr, u32 mask)
    {
        u32 new_mask;
        new_mask = FSPI_READREG32(base_addr, FSPI_IMR_OFFSET) & ~mask;
        FSPI_WRITEREG32(base_addr, FSPI_IMR_OFFSET, new_mask);
    }

    static _INLINE void FSpiIrqUmask(u32 base_addr, u32 mask)
    {
        u32 new_mask;
        new_mask = FSPI_READREG32(base_addr, FSPI_IMR_OFFSET) | mask;
        FSPI_WRITEREG32(base_addr, FSPI_IMR_OFFSET, new_mask);
    }

    static _INLINE void FSpiResetChip(u32 base_addr)
    {
        FSPI_WRITEREG32(base_addr, FSPI_SSIENR_OFFSET, 0);
        FSpiIrqMask(base_addr, 0xff); // mask irq
        FSPI_WRITEREG32(base_addr, FSPI_SER_OFFSET, 0x1);
        FSPI_WRITEREG32(base_addr, FSPI_SSIENR_OFFSET, 1); // Set Microwire mod
    }

    static _INLINE void FSpiShutdownChip(u32 base_addr)
    {
        FSPI_WRITEREG32(base_addr, FSPI_SSIENR_OFFSET, 0);
        FSPI_WRITEREG32(base_addr, FSPI_BAUD_R_OFFSET, 0); // mask irq
    }

    static _INLINE void FSpiEnableChip(u32 base_addr, u32 enable)
    {
        FSPI_WRITEREG32(base_addr, FSPI_SSIENR_OFFSET, enable ? 1 : 0);
    }

    static _INLINE void FSpiSetClk(u32 base_addr, u16 div)
    {
        FSPI_WRITEREG32(base_addr, FSPI_BAUD_R_OFFSET, div);
    }

#ifdef __cplusplus
}
#endif

#endif // !